﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Data;

using LibSnesDotNet.Input;

namespace LibSnesDotNet.UI
{
	public class InputIDBindingsControl : UserControl
	{
		#region Dependency Properties

		static DependencyProperty InputIDBindingsProperty =
			DependencyProperty.Register("InputIDBindings", typeof(InputBindingElementCollection), typeof(InputIDBindingsControl),
			                            new PropertyMetadata(null, InputIDBindingsChangedCallback));
		static void InputIDBindingsChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			var sThis = (InputIDBindingsControl)d;

			if (!sThis.IsLoaded) { return; }

			if (sThis.Template != null)
			{
				sThis.GetInputIDBindingsList().ItemsSource = (InputBindingElementCollection)e.NewValue;
			}
		}
		public InputBindingElementCollection InputIDBindings
		{
			get { return (InputBindingElementCollection)GetValue(InputIDBindingsProperty); }
			set { SetValue(InputIDBindingsProperty, value); }
		}

		static DependencyProperty MessageProperty = DependencyProperty.Register("Message", typeof(string), typeof(InputIDBindingsControl),
		                                                                        new PropertyMetadata("Waiting for input..."));
		public string Message
		{
			get { return (string)GetValue(MessageProperty); }
			set { SetValue(MessageProperty, value); }
		}

		static DependencyProperty DimensionalityProperty = DependencyProperty.Register("Dimensionality", typeof(InputDimensionality), typeof(InputIDBindingsControl),
		                                                                               new PropertyMetadata(InputDimensionality.Digital));
		public InputDimensionality Dimensionality
		{
			get { return (InputDimensionality)GetValue(DimensionalityProperty); }
			set { SetValue(DimensionalityProperty, value); }
		}

		#endregion

		static ReportInputDialog _dialog = new ReportInputDialog();

		public InputIDBindingsControl()
		{
			CommandBindings.Add(new CommandBinding(ApplicationCommands.New, New_Execute, New_CanExecute));
			CommandBindings.Add(new CommandBinding(ApplicationCommands.Delete, Delete_Execute, Delete_CanExecute));
		}

		bool ReportInputPredicate(InputReceivedEventArgs e)
		{
			if (e.Input.Dimensionality != Dimensionality) { return false; }

			switch (e.Input.Dimensionality)
			{
				case InputDimensionality.Digital:
					return ((DigitalInputReceivedEventArgs)e).State;

				case InputDimensionality.Linear:
				case InputDimensionality.Planar:
					return true;

				default:
					return false;
			}
		}

		ItemsControl GetInputIDBindingsList()
		{
			var x = (ItemsControl)this.Template.FindName("PART_InputIDBindings", this);
			return x;
		}

		public override void  OnApplyTemplate()
		{
			base.OnApplyTemplate();

			GetInputIDBindingsList().ItemsSource = InputIDBindings;
		}

		void New_CanExecute(object sender, CanExecuteRoutedEventArgs e)
		{
			if (e.Source != this) { return; }

			ItemsControl list = GetInputIDBindingsList();
			e.CanExecute = list != null && list.Items.SourceCollection is InputBindingElementCollection;

			e.Handled = true;
		}

		void New_Execute(object sender, ExecutedRoutedEventArgs e)
		{
			_dialog.Message = Message;
			_dialog.Predicate = ReportInputPredicate;
			if (_dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
			{
				ItemsControl list = GetInputIDBindingsList();
				((InputBindingElementCollection)list.Items.SourceCollection).Add(new InputBindingElement() { Input = _dialog.InputID });
				list.Items.MoveCurrentToLast();
			}

			e.Handled = true;
		}

		void Delete_CanExecute(object sender, CanExecuteRoutedEventArgs e)
		{
			if (e.Source != this) { return; }

			ItemsControl list = GetInputIDBindingsList();
			e.CanExecute = list != null && list.Items.SourceCollection is InputBindingElementCollection && list.Items.CurrentItem != null;

			e.Handled = true;
		}

		void Delete_Execute(object sender, ExecutedRoutedEventArgs e)
		{
			if (e.Source != this) { return; }
			ItemsControl list = GetInputIDBindingsList();
			((InputBindingElementCollection)list.Items.SourceCollection).Remove((InputBindingElement)list.Items.CurrentItem);

			e.Handled = true;
		}

	}
}
